//
//  ViewController.m

//
//  Created by Scott on 16/1/6.
//  Copyright © 2016年 Scott. All rights reserved.
//

#import "ViewController.h"

@interface ViewController () <NSURLSessionDelegate, NSURLSessionDataDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate>

// 用来接收网络数据.
@property (nonatomic, retain) NSMutableData *data;

@property (nonatomic, retain) NSURL *downloadURL;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    [self initData];
    
    [self addDownloadSubviews];

}

/**
 * NSURLSession 原理
 *
 * iOS 7.0之前的网络是用NSURLConnection类负责链接服务器, 从服务器发送请求获取数据.
 * iOS 7.0之后推出新的NSURLSession替换NSURLConnection类, iOS9.0之后, NSURLConnection将彻底放弃.
 *
 * NSURLSession原理是客户端和服务器端建立一个session, 在一个session中添加一系列的task(任务,任务有三种:dataTask(普通数据任务), uploadTask(上传任务), downLoadTask(下载任务)).
 *
 * NSURLSessionConfiguration类是用来配置session的一些特性.
 *
 * NSURLSession 采用是异步形式, 数据可以通过delegate和block两种方式回调.
 *
 * 参考API: NSURLSession, NSURLSessionConfiguration, NSURLSessionTask
 */


#pragma mark - 知识点1 get获取数据, 通过block回调
- (IBAction)handleGETByBlock:(id)sender {
    
    // URL
    NSURL *url = [NSURL URLWithString:@"http://mobile.ximalaya.com/m/explore_album_list?category_name=all&condition=hot&device=android&page=1&per_page=20&status=0&tag_name=%E5%8D%81%E4%BA%8C%E6%98%9F%E5%BA%A7"];
    
    // 创建session对象(通道)
    NSURLSession *session = [NSURLSession sharedSession];
    
    
    // 创建任务(task)
    NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        // block中的参数, 就是从服务器获取的数据.
        NSLog(@"%@", response);
        
        // data进行解析(JSON格式)
        NSError *errorOfJSON = nil;
        id result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&errorOfJSON];
        
        
        NSLog(@"%@", result);
        
        NSLog(@"data:%@", data);
        
        NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        
        NSLog(@"%@", str);
        
    }];
    
    
    // 开始任务. 必须调用此方法, 任务才开始执行.
    [task resume];
    
}

#pragma mark - 知识点2 get获取数据, 通过delegate回调
- (IBAction)handleGETByDelegate:(id)sender {
    
    self.data = [NSMutableData data];
    
    // URL
    NSURL *url = [NSURL URLWithString:@"http://mobile.ximalaya.com/m/explore_album_list?category_name=all&condition=hot&device=android&page=1&per_page=20&status=0&tag_name=%E5%8D%81%E4%BA%8C%E6%98%9F%E5%BA%A7"];
    
    // 创建session对象(通道)
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    
    // 添加任务
    NSURLSessionDataTask *task = [session dataTaskWithURL:url];
    
    
    // 开始任务
    [task resume];
}

#pragma mark - 协议方法
/** 当从服务器收到响应的时候, 调用此方法. */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    
    NSLog(@"dataTask:%@", dataTask);
    
    NSLog(@"%@", response);
    
    completionHandler(NSURLSessionResponseAllow);
}

/** 当接收数据时候, 调用此方法. 此方法可能会调用多次 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    
    // 将数据进行拼接
    [self.data appendData:data];
    
}

/** 当任务完成时候, 调用此方法. */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    
    // 解析
    NSError *errorOfJSON = nil;
    id result = [NSJSONSerialization JSONObjectWithData:self.data options:NSJSONReadingMutableContainers error:&errorOfJSON];
    
    if (result != nil) {
        NSLog(@"%@", result);
    }
}


#pragma mark - 知识点3 POST 获取数据,Block回调
- (IBAction)handlePOSTByBlock:(id)sender {
    
    // URL
    NSURL *url = [NSURL URLWithString:@"http://ipad-bjwb.bjd.com.cn/DigitalPublication/publish/Handler/APINewsList.ashx?date=20131129&startRecord=1&len=15&udid=1234567890&terminalType=Iphone&cid=213"];
    
    // URLRequest(网络请求对象)
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    request.HTTPMethod = @"POST";
    
    request.HTTPBody = [@"username=daka&pwd=123" dataUsingEncoding:NSUTF8StringEncoding];
    
    // session对象(通道)
    NSURLSession *session = [NSURLSession sharedSession];
    
    // 添加任务
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        // 解析
        NSError *errorOfJSON = nil;
        id result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&errorOfJSON];
        
        NSLog(@"%@", result);
        
    }];
    
    // 开始任务
    [task resume];
}


#pragma mark - 知识点4 POST 获取数据, Delegate回调
- (IBAction)handlePOSTByDelegate:(id)sender {
    
    // URL
    NSURL *url = [NSURL URLWithString:@"http://ipad-bjwb.bjd.com.cn/DigitalPublication/publish/Handler/APINewsList.ashx?date=20131129&startRecord=1&len=15&udid=1234567890&terminalType=Iphone&cid=213"];
    
    // URLRequest
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    request.HTTPMethod = @"POST";
    request.HTTPBody = [@"username=daka&pwd=123" dataUsingEncoding:NSUTF8StringEncoding];
    
    // Session(通道)
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    // 添加任务
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
    
    // 开始任务
    [task resume];
    
}


/** 数据初始化 */
- (void)initData {
    
    self.data = [NSMutableData data];
    
    // 视频, 方便看到下载过程
    self.downloadURL = [NSURL URLWithString:@"http://us.sinaimg.cn/003kyKo0jx06VEIpDJgA05040100WKL30k01.mp4"];
    // 视频来源: 新浪微博秒拍解析地址后获得真实地址, 若失效, 自己找一个~
    // 微博视频地址在线解析: http://www.weibovideo.com
    
    // 图片
    //    self.downloadURL = [NSURL URLWithString:@"http://www.iconfont.cn/uploads/fonts/font-347832-.png?color=272636&size"];
    
}


/** 添加页面下载button */
- (void)addDownloadSubviews {
    UIButton *blockBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.view addSubview:blockBtn];
    
    blockBtn.frame = CGRectMake((self.view.frame.size.width - 270) / 2, 387, 270, 46);
    [blockBtn setTitle:@"Download(Block)" forState:UIControlStateNormal];
    [blockBtn setTitleColor:[UIColor colorWithRed:48/255.0 green:117/255.0 blue:250/255.0 alpha:1] forState:UIControlStateNormal];
    blockBtn.titleLabel.font = [UIFont fontWithName:@"Arial" size:30];
    
    [blockBtn addTarget:self action:@selector(downloadByBlock) forControlEvents:UIControlEventTouchUpInside];
    
    
    UIButton *delegateBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.view addSubview:delegateBtn];
    
    delegateBtn.frame = CGRectMake((self.view.frame.size.width - 300) / 2, 433, 300, 46);
    [delegateBtn setTitle:@"Download(Delegate)" forState:UIControlStateNormal];
    [delegateBtn setTitleColor:[UIColor colorWithRed:48/255.0 green:117/255.0 blue:250/255.0 alpha:1] forState:UIControlStateNormal];
    delegateBtn.titleLabel.font = [UIFont fontWithName:@"Arial" size:30];
    
    [delegateBtn addTarget:self action:@selector(downloadByDelegate) forControlEvents:UIControlEventTouchUpInside];
}


#pragma mark - 知识点5 添加 #160129_WY 下载数据, Block回调
- (void)downloadByBlock {
    // Session(通道)
    NSURLSession *session = [NSURLSession sharedSession];
    
    // 添加任务
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:self.downloadURL completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        // 服务器返回信息, 响应头 状态码 URL等
        NSLog(@"%@", response);
        
        // 文件默认下载位置, 在tmp目录下
        NSLog(@"%@", location);
        
        // 设置本地路径, 注意路径格式中的file://
        NSURL *goalLocation = [NSURL URLWithString:[@"file://" stringByAppendingString:[NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/1.%@", self.downloadURL.pathExtension]]]];
        
        NSLog(@"%@", goalLocation);
        
        // 从tmp目录下转存至指定目录, 会删除tmp下文件.
        NSError *errorOfFileCopy = nil;
        [[NSFileManager defaultManager] copyItemAtURL:location toURL:goalLocation error:&errorOfFileCopy];
    }];
    
    // 开始任务
    [task resume];
}


#pragma mark - 知识点6 添加 #160129_WY 下载数据, Delegate回调
/**
 * 1. 签协议, NSURLSessionDownloadDelegate
 */
- (void)downloadByDelegate {
    // 2. Session(通道), 采用默认配置
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    // 3. 添加任务
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:self.downloadURL];
    
    // 4. 开始任务
    [task resume];
}

#pragma mark - 协议方法
/**
 * 5. 实现协议方法
 */
/** 完成下载时会执行该方法, 转存文件至自定义文件夹, 必须实现 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    
    NSLog(@"%@", location);
    
    NSURL *goalLocation = [NSURL URLWithString:[@"file://" stringByAppendingString:[NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/1.%@", self.downloadURL.pathExtension]]]];
    
    NSError *errorOfFileCopy = nil;
    
    [[NSFileManager defaultManager] copyItemAtURL:location toURL:goalLocation error:&errorOfFileCopy];
    
}
/** 实时监控下载状态, 可显示下载进度, 选择实现 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    NSLog(@"已传输的字节数:%lld", totalBytesWritten);
    NSLog(@"共需传输字节数:%lld", totalBytesExpectedToWrite);
}

#pragma mark -
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
